<?php

namespace App\Console\Commands;

use App\Constant\JpushCode;
use App\Events\JpushNoticeEvent;
use App\Facades\CommonPlatformRequestFacade;
use App\Facades\MoneyPlatformRequestFacade;
use App\Jobs\RepayBuckleJob;
use App\Jobs\RepayCommonJob;
use App\Jobs\RepayJcfcSyncJob;
use App\Jobs\RepayMoneyJob;
use App\Jobs\RepayMoneyNotifyJob;
use App\Jobs\RepayMonthJob;
use App\Library\ArrayTools\ArrayTools;
use App\Models\LoanApply as LoanApplyModel;
use App\Models\RepayRecord;
use App\Models\RepayRecordCommon;
use App\Models\RepayRecordMoney;
use App\Models\RepayRecordMonth;
use App\Models\RepaySummary;
use App\Models\SettingChannel;
use App\Models\UserLoanRequest;
use App\ModelTransfers\WsFund\UniFundOrder;
use Carbon\Carbon;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;

class RepayCommand extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'repay:cron {action : month|common|money|JRepay|JOverdue|upFines|help|buckle|jsSync|initLoan|moneyNotify|supplyCommonPayOrderNo|supplyMoneyPayOrderNo|rawDataUpdateChannel}';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Repay cron relevant';

    /**
     * The console command action. month|common|money|help
     *
     * @var string
     */
    protected $action;


    /**
     * Execute the console command.
     *
     * @return mixed
     */
    public function handle()
    {
        $this->initAction();
        $this->runAction();
    }


    /**
     * Description: 月报api接口查询
     * Author: Gxs
     */
    public function month()
    {
        foreach (RepayRecordMonth::where('status', RepayRecordMonth::STATUS_TWO)->cursor() as $key => $model) {
            RepayMonthJob::dispatch($model->id);
        };
        $this->info('month api done');
    }

    /**
     * Description: 公共api接口查询
     * Author: Gxs
     */
    public function common()
    {
        foreach (RepayRecordCommon::where('status', RepayRecordCommon::STATUS_TWO)->cursor() as $key => $model) {
            RepayCommonJob::dispatch($model->id);
        };
        $this->info('common api done');
    }

    /**
     * Description: 资金api接口查询
     * Author: Gxs
     */
    public function money()
    {
        foreach (RepayRecordMoney::where('status', RepayRecordMoney::STATUS_TWO)->cursor() as $key => $model) {
            RepayMoneyJob::dispatch($model->id);
        };
        $this->info('money api done');
    }

    /**
     * 裸扣结果查询
     */
    public function buckle(){
        foreach (RepayRecord::where('status', RepayRecord::STATUS_TWO)->where('buckle_type',RepayRecord::BUCKLE_TYPE_ONE)->cursor() as $key => $model) {
            RepayBuckleJob::dispatch($model);
        };
        $this->info('buckle api done');
    }

    /**
     * Description: 极光推送 还款提醒条件: 距离还款日期3天, 跳转到借款记录, 执行时间每天早晨9点
     * Author: Gxs
     */
    public function JRepay()
    {
        $title = '还款提醒';
        $msg = "您的第%s期还款日还有3天,请留意,点击了解账单详情.";
        $after_three_days = Carbon::parse('+3 days')->toDateString();
        foreach (RepayRecord::where([
            ['normal_date', '=', $after_three_days],
            ['status', '<>', RepayRecord::STATUS_FOUR],
            ['period', '<>', 0],
        ])->cursor() as $record) {
            $jpush_registration_id = $record->relationUserGlobals->jpush_registration_id;
            if (empty($jpush_registration_id)) //没有jpush registration_id 不能推送
                continue;
            $msg = sprintf($msg, $record->period);
            event(new JpushNoticeEvent([
                'body' => $msg,
                'title' => $title,
                'audience' => JpushCode::AUDIENCE_TYPE_TWO,
                'to' => [$jpush_registration_id],
                'extras' => [
                    'jump_type' => JpushCode::EXTRAS_JUMP_TYPE_TWO
                ],
            ]));
        }
        $this->info('Jpush repay done');
    }

    /**
     * Description: 今日还款提醒 还款提醒条件: 今天为还款日期, 跳转到借款记录, 执行时间每天早晨9点
     * Author: Gxs
     */
    public function JToday()
    {
        $title = '还款提醒';
        $msg = "今天是您的第%s期还款日，请及时还款.";
        $current_date = Carbon::now()->toDateString();
        foreach (RepayRecord::where([
            ['normal_date', '=', $current_date],
            ['status', '<>', RepayRecord::STATUS_FOUR],
            ['period', '<>', 0],
        ])->cursor() as $record) {
            $jpush_registration_id = $record->relationUserGlobals->jpush_registration_id;
            if (empty($jpush_registration_id)) //没有jpush registration_id 不能推送
                continue;
            $msg = sprintf($msg, $record->period);
            event(new JpushNoticeEvent([
                'body' => $msg,
                'title' => $title,
                'audience' => JpushCode::AUDIENCE_TYPE_TWO,
                'to' => [$jpush_registration_id],
                'extras' => ['jump_type' => JpushCode::EXTRAS_JUMP_TYPE_TWO],
            ]));
        }
        $this->info('Jpush today done');
    }

    /**
     * Description: 逾期提醒 跳转到借款记录 && 罚息提醒 跳转到首页, 执行时间每天早晨9点
     * Author: Gxs
     */
    public function JOverdue()
    {
        $title = '逾期提醒';
        $msg1 = "您的第%s期还款已逾期%s天,未避免产生不必要的损失,请您及时还款.";
        $msg2 = "由于您未及时偿还本期欠款,已经出现逾期并产生罚息,请您及时还款.";
        $current_date = Carbon::now()->toDateString();
        foreach (RepayRecord::where([
            ['normal_date', '<', $current_date],
            ['status', '<>', RepayRecord::STATUS_FOUR],
            ['period', '<>', 0],
        ])->cursor() as $record) {
            $jpush_registration_id = $record->relationUserGlobals->jpush_registration_id;
            if (empty($jpush_registration_id)) //没有jpush registration_id 不能推送
                continue;
            event(new JpushNoticeEvent([
                'body' => $msg2,
                'title' => $title,
                'audience' => JpushCode::AUDIENCE_TYPE_TWO,
                'to' => [$jpush_registration_id],
                'extras' => ['jump_type' => JpushCode::EXTRAS_JUMP_TYPE_ONE],
            ]));
            $current_date = Carbon::now();
            $normal_date = Carbon::createFromFormat('Y-m-d', $record->normal_date);
            $overdue_day = $normal_date->diffInDays($current_date, false); //逾期天数
            $msg = sprintf($msg1, $record->period, $overdue_day);
            event(new JpushNoticeEvent([
                'body' => $msg,
                'title' => $title,
                'audience' => JpushCode::AUDIENCE_TYPE_TWO,
                'to' => [$jpush_registration_id],
                'extras' => ['jump_type' => JpushCode::EXTRAS_JUMP_TYPE_TWO],
            ]));

        };
        $this->info('Jpush overdue done');
    }

    /**
     * Description: 罚息数据每日定时更新
     * Author: Gxs
     */
    public function upFines()
    {
        $current_date = Carbon::now()->format('Y-m-d');
        RepayRecord::leftJoin('repay_summaries as a', 'repay_records.summary_id', '=', 'a.id')
            ->leftJoin('repay_record_moneys as b', 'repay_records.id', '=', 'b.record_id')
            ->leftJoin('repay_record_commons as c', 'repay_records.id', '=', 'c.record_id')
            ->select([
                'a.loan_id',
                'a.loan_channel',
                'a.rate',
                'a.amount as summary_amount',
                'b.status as money_status',
                'c.status as common_status',
                'repay_records.id',
                'repay_records.summary_id', //todo 垃圾获取器
                'repay_records.normal_date',
                'repay_records.period as record_period'
            ])
            ->whereIn('repay_records.status', [RepayRecord::STATUS_ONE, RepayRecord::STATUS_THREE])
            ->where('repay_records.normal_date', '<', $current_date)
            //todo 修复period = 0 有罚息的数据
            ->where('repay_records.period', '>', 0) //todo 加上索引
//            ->where('repay_records.id', 261229) //测试条件
            ->chunk(1000, function ($records) {
                foreach ($records as $key=>$model) {
                    Log::debug('update_fines_log', ['record_id' => $model['id']]);
                    try {
                        $rate = json_decode($model['rate'], true);
                        $model['fines_rate'] = $rate['fines_rate'];
                        $fine_result = RepaySummary::getSimpleFines($model);
                        $common_fines_money = bcmul($fine_result['common_fines_money'], 100, 2);
                        $money_fines_money = bcmul($fine_result['money_fines_money'], 100, 2);
                        if ($money_fines_money > 0) {
                            DB::table('repay_record_moneys')->where('record_id', $model['id'])->update([
                                'fines_money' => $money_fines_money,
                            ]);
                        }
                        if ($common_fines_money > 0) {
                            DB::table('repay_record_commons')->where('record_id', $model['id'])->update([
                                'fines_money' => $common_fines_money,
                            ]);
                        }
                    } catch (\Exception $e) {
                        Log::debug('update_fines_exception', [
                            'record_id' => $model['id'],
                            'file' => $e->getFile(),
                            'line' => $e->getLine(),
                            'message' => $e->getMessage(),
                        ]);
                        continue ;
                    }
                }
            });
        $this->info('update fines done');
    }

    /**
     * Description: 更新新卡贷数据,放款成功未生成还款记录处理脚本
     * Author: Gxs
     */
    public function initLoan()
    {
        foreach (LoanApplyModel::whereNotExists(function ($query) {
            $query->select(DB::raw('id FROM repay_summaries WHERE repay_summaries.loan_request_id = loan_apply.loan_request_id'));
        })
            ->where('loan_status', 2)
            ->cursor() as $loan) {
            $result = RepaySummary::initRepaySummary($loan);
            $this->info($result);
        }
        $this->info('init loan done');
    }

    /**
     * Description: 修复补充资方京东流水号
     * Author: Gxs
     */
    public function supplyMoneyPayOrderNo()
    {
        //查找为空的值
        RepayRecordMoney::where(function ($query) {
            $query->where('pay_order_no', '=', '')
                ->orWhereNull('pay_order_no');
        })
            ->where('status', RepayRecordMoney::STATUS_FOUR)
            ->where('third_repay_id', '<>', '')
            ->where('trade_no', '<>', '')
            ->chunk(2000, function ($moneys) {
                foreach ($moneys as $money) {
                    //获取还款计划表
                    $result = MoneyPlatformRequestFacade::getMoneyRepayResult([
                        'third_repay_id' => $money['third_repay_id'],
                        'trade_no' => $money['trade_no'],
                    ]);
                    if (false != $result) {
                        $data = $result['data'];
                        $money->pay_order_no = isset($data['payOrderNo']) ? $data['payOrderNo'] : ''; //京东商户订单号
                        $money->save();
                    }
                }
            });
        $this->info('supply money pay order no done');
    }

    /**
     * Description: 修复补充公共京东流水号
     * Author: Gxs
     */
    public function supplyCommonPayOrderNo()
    {
        RepayRecordCommon::where(function ($query) {
            $query->where('pay_order_no', '=', '')
                ->orWhereNull('pay_order_no');
        })
            ->where('status', RepayRecordCommon::STATUS_FOUR)
            ->where('third_record_id', '<>', '')
            ->where('trade_no', '<>', '')
            ->chunk(2000, function ($commons) {
                foreach ($commons as $common) {
                    //获取还款计划表
                    $result = CommonPlatformRequestFacade::getCommonRepayResult([
                        'channelId' => $common['third_record_id'],
                        'orderId' => $common['trade_no'],
                    ]);
                    if (false != $result) {
                        $data = $result['data'];
                        $common->pay_order_no = isset($data['payOrderNo']) ? $data['payOrderNo'] : ''; //京东商户订单号
                        $common->save();
                    }
                }
            });
        $this->info('supply common pay order no done');
    }

    /**
     * Description: help
     * Author: Gxs
     */
    public function help()
    {
        $this->showHelp();
    }

    /**
     * Description: Initialize command action.
     * Author: Gxs
     */
    protected function initAction()
    {
        $this->action = $this->argument('action');
        if (!in_array($this->action, [
            'month', 'common', 'money', 'JRepay', 'JToday', 'JOverdue','upFines','help','buckle','jsSync',
            'initLoan','moneyNotify','supplyCommonPayOrderNo','supplyMoneyPayOrderNo', 'rawDataUpdateChannel'
        ])) {
            $this->error("Invalid argument '{$this->action}'. Expected 'month', 'common', 'money', 'help', 'jsSync', 'initLoan', 'supplyCommonPayOrderNo', 'supplyMoneyPayOrderNo'");
            exit(1);
        }
    }

    /**
     * Description: Run action.
     * Author: Gxs
     */
    protected function runAction()
    {
        $this->{$this->action}();
    }

    /**
     * Description: show help
     * Author: Gxs
     */
    protected function showHelp()
    {
        $table = [
            ['PHP Version', 'Version' => phpversion()],
            ['Laravel Version', $this->getApplication()->getVersion()],
            ['month', 'cron for third month api result'],
            ['common', 'cron for third common api result'],
            ['money', 'cron for third money api result'],
            ['JRepay', 'cron for Jpush repay early warning push message'],
            ['JToday', 'cron for Jpush repay today warning push message'],
            ['JOverdue', 'cron for Jpush repay overdue warning push message'],
            ['jsSync', 'cron for Jinshang data sync'],
            ['help', '--help'],
        ];
        $this->table(['Name', 'Value'], $table);
    }

    /**
     * 晋商逾期的数据需要同步到表中
     *
     * @return bool
     */
    protected function jsSync()
    {
        //跑批逻辑
        $repaySummaryInfo = RepaySummary::with(['recordOne'=>function($q){
            $today = Carbon::today();
            $q->where('status','<>',RepayRecord::STATUS_FOUR);
            $q->where('status','<>',RepayRecord::STATUS_TWO);
            $q->where('pay_off',RepayRecord::PAY_OFF_ONE);
            $q->whereDate('normal_date','<=',$today->toDateString());
        },'recordOne.money' => function($q){
            $q->where('status','<>',RepayRecordMoney::STATUS_TWO);
            $q->where('status','<>',RepayRecordMoney::STATUS_FOUR);
        }])
            ->where('repay_summaries.status',RepaySummary::STATUS_ONE)
            ->chunk(2000, function ($repaySummaryInfo) {
                if(!empty($repaySummaryInfo)){
                    foreach ($repaySummaryInfo as $k => $value){
                        if(empty($value->recordOne) || empty($value->recordOne->money)){
                            continue;
                        }
                        $today = Carbon::today();
                        $normal_date = Carbon::parse($value->recordOne->normal_date);
                        if($today->lt($normal_date)){
                            continue;
                        }

                        $is_channel = $this->isJinShang($value);
                        if(!$is_channel){
                            continue;
                        }
                        $money = $value->recordOne->money;
                        if($money->status != RepayRecordMoney::STATUS_ONE && $money->status != RepayRecordMoney::STATUS_THREE){
                            continue;
                        }
                        RepayJcfcSyncJob::dispatch($value->recordOne);
                    }
                }
            });

    }


    protected function isJinShang(RepaySummary $summaryInfo)
    {
        if($summaryInfo->data_type == RepaySummary::DATA_TYPE_ONE){
            if($summaryInfo->relationUserLoanRequests->channel == SettingChannel::CHANNEL_JIXIAO){
                return true;
            }
        }elseif($summaryInfo->data_type == RepaySummary::DATA_TYPE_TWO){
            if($summaryInfo->loan_channel == 'LCC201709190010'){
                return true;
            }
        }
        return false;

    }


    public function moneyNotify(){
        $commonInfo = RepayRecordCommon::where('status',RepayRecordCommon::STATUS_FOUR)->where('money_notify_status',RepayRecordCommon::MONEY_NOTIFY_STATUS_TWO)->chunk(1000, function ($commonInfo) {
            foreach ($commonInfo as $value) {
                RepayMoneyNotifyJob::dispatch($value);
            }
        });
    }

    /**
     * Description: 原卡贷数据(更新渠道)区分晋商,新光大
     * Author: Gxs
     */
    public function rawDataUpdateChannel()
    {
        UserLoanRequest::leftJoin('repay_summaries as b', 'user_loan_requests.id', '=', 'b.loan_request_id')
            ->where('b.data_type', RepaySummary::DATA_TYPE_TWO)
            ->where('b.loan_channel', 'LCC201709190010')
            ->select(['user_loan_requests.id','b.trans_id'])
            ->chunk(2000, function ($loans) {
                $trans_ids = $loans->pluck('trans_id');
                $orders = UniFundOrder::whereIn('apply_id', $trans_ids)
                    ->select(['apply_id', 'channel_data'])
                    ->get()->toArray();
                if (!empty($orders)) {
                    $orders = ArrayTools::valueToKey($orders, 'apply_id');
                    foreach ($loans as $loan) {
                        if (isset($orders[$loan->trans_id])) {
                            $temp = $orders[$loan->trans_id];
                            if (isset($temp['channel_data']['finalFundChannel'])) {
                                $loan->channel = $temp['channel_data']['finalFundChannel'];
                                $loan->save();
                                $this->info('id:' . $loan->id . 'update success');
                            } else {
                                Log::debug('raw_data_update_channel', ['result'=>$temp]);
                                $this->info('id:' . $loan->id . 'update failure');
                            }
                        }
                    }
                }
            });
        $this->info('raw data update channel');
    }
}